package flower.home.common.poi;

import lombok.Data;
import org.apache.commons.collections.CollectionUtils;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.xssf.usermodel.XSSFRelation;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * 参考：org.apache.poi.xssf.eventusermodel.ReadOnlySharedStringsTable
 * 去除读取rPh节点
 *
 * @author Administrator
 */
@Data
public class ReadOnlySharedStringsTable extends DefaultHandler {

    public ReadOnlySharedStringsTable(OPCPackage pkg)
            throws IOException, SAXException {
        ArrayList parts = pkg.getPartsByContentType(XSSFRelation.SHARED_STRINGS.getContentType());
        if (parts.size() > 0) {
            PackagePart sstPart = (PackagePart) parts.get(0);
            readFrom(sstPart.getInputStream());
        }
    }

    private void readFrom(InputStream is)
            throws IOException, SAXException {
        InputSource sheetSource = new InputSource(is);
        SAXParserFactory saxFactory = SAXParserFactory.newInstance();
        try {
            SAXParser saxParser = saxFactory.newSAXParser();
            XMLReader sheetParser = saxParser.getXMLReader();
            sheetParser.setContentHandler(this);
            sheetParser.parse(sheetSource);
        } catch (ParserConfigurationException e) {
            throw new RuntimeException("SAX parser appears to be broken - " + e.getMessage());
        }
    }

    @Override
    public void startElement(String uri, String localName, String name, Attributes attributes) {
        switch (name) {
            case "sst":
                String count = attributes.getValue("count");
                if (count != null) {
                    this.count = Integer.parseInt(count);
                }
                String uniqueCount = attributes.getValue("uniqueCount");
                if (uniqueCount != null) {
                    this.uniqueCount = Integer.parseInt(uniqueCount);
                }
                items = new ArrayList<>(this.uniqueCount);
                characters = new StringBuffer();
                break;
            case "si":
                characters.setLength(0);
                break;
            case "t":
                tIsOpen = true;
                break;
            case "rPh":
                rPhIsOpen = true;
                break;
            default:
        }
    }

    @Override
    public void endElement(String uri, String localName, String name) {
        switch (name) {
            case "si":
                if (CollectionUtils.isEmpty(items)) {
                    items = new ArrayList<>();
                }
                items.add(characters.toString());
                break;
            case "t":
                tIsOpen = false;
                break;
            case "rPh":
                rPhIsOpen = false;
                break;
            default:
        }
    }

    @Override
    public void characters(char[] ch, int start, int length) {
        if (tIsOpen && !rPhIsOpen) {
            characters.append(ch, start, length);
        }
    }

    private int count;
    private int uniqueCount;
    private List<String> items;
    private StringBuffer characters;
    private boolean tIsOpen;
    private boolean rPhIsOpen;
}
